#include "ConnectionPool.h"
#include <QThread>
#include <QDebug>
#include <QtSql/QSqlError>
#include <QtSql/QSqlQuery>
#include "helper/ConfigHelper.h"

ConnectionPool::ConnectionPool(QObject* parent)
    : QObject(parent), m_activeCount(0), m_maxConn(10) {}

ConnectionPool::~ConnectionPool()
{
    QMutexLocker lock( & m_mutex);
    // 清理所有空闲连接
    while (!m_available.isEmpty())
    {
        QString connName = m_available.dequeue().name;
        QSqlDatabase::removeDatabase(connName);
    }
}

void ConnectionPool::initialize()
{
    loadConfig();

    // 初始化最小连接数
    int prewarmCount = ConfigHelper::instance().getInt("database", "prewarm", 3);
    for(int i = 0; i < prewarmCount; ++i)
    {
        QSqlDatabase db = createConnection();
        if(db.isValid())
        {
            m_available.enqueue({db.connectionName(), QDateTime::currentDateTime()});
        }
    }
}

QSqlDatabase ConnectionPool::getConnection(int retries)
{
    QElapsedTimer timer;
    timer.start();

    for(int attempt = 0; attempt < retries; ++attempt)
    {
        QMutexLocker lock( & m_mutex);

        // 阶段1：尝试复用现有连接
        while(!m_available.isEmpty())
        {
            ConnInfo info = m_available.dequeue();
            QSqlDatabase db = QSqlDatabase::database(info.name);

            if(validateConnection(db))
            {
                m_activeCount.ref();
                return db;
            }
            else
            {
                QSqlDatabase::removeDatabase(info.name);
            }
        }

        // 阶段2：创建新连接
        if(m_activeCount < m_maxConn)
        {
            QSqlDatabase db = createConnection();
            if(db.isValid())
            {
                m_activeCount.ref();
                return db;
            }
        }

        // 阶段3：等待释放
        if(!m_cond.wait( & m_mutex, qMax<qint64>(100, 5000 - timer.elapsed())))
        {
            qWarning() << "Connection wait timeout (attempt" << attempt + 1 << ")";
        }
    }
    throw std::runtime_error("Failed to acquire database connection");
}

void ConnectionPool::releaseConnection(QSqlDatabase conn)
{
    if (!conn.isValid()) return;

    // 清理会话状态
    cleanupSession(conn);

    QMutexLocker lock( & m_mutex);

    // SQLite 特殊处理：避免过多空闲连接
    if (m_type == SQLite && m_available.size() >= 1)
    {
        // 只保留一个空闲连接给 SQLite
        QSqlDatabase::removeDatabase(conn.connectionName());
    }
    else if (m_available.size() < m_maxConn * 0.8)
    {
        m_available.enqueue({conn.connectionName(), QDateTime::currentDateTime()});
    }
    else
    {
        QSqlDatabase::removeDatabase(conn.connectionName());
    }

    m_activeCount.deref();
    m_cond.wakeOne();
}

void ConnectionPool::setValidationQuery(const QString& query)
{
    QMutexLocker lock( & m_mutex); // 线程安全操作
    m_validationQuery = query;

    // 可选：立即验证现有连接
    foreach(const auto& connInfo, m_available)
    {
        QSqlDatabase db = QSqlDatabase::database(connInfo.name);
        validateConnection(db); // 强制验证
    }
}

int ConnectionPool::activeConnections() const
{
    QMutexLocker lock( & m_mutex); // 加锁保证线程安全
    return m_available.size();    // 直接返回队列大小
}

int ConnectionPool::idleConnections() const
{
    QMutexLocker lock( & m_mutex); // 加锁保证线程安全
    return m_available.size();    // 直接返回队列大小
}

// 数据库差异实现
QString ConnectionPool::driverName() const
{
    switch(m_type)
    {
        case SQLite:
            return "QSQLITE";
        case MySQL:
            return "QMYSQL";
        case MariaDB:
            return "QMARIADB";
        case PostgreSQL:
            return "QPSQL";
        case Oracle:
            return "QOCI";
        case ODBC:
            return "QODBC";
        default:
            throw std::runtime_error("Unsupported driver");
    }
}

QString ConnectionPool::getDefaultValidationQuery() const
{
    switch(m_type)
    {
        case SQLite:
            return "SELECT 1";
        case MySQL:
            return "SELECT 1";
        case MariaDB:
            return "SELECT 1";
        case PostgreSQL:
            return "SELECT 1";
        case Oracle:
            return "SELECT 1 FROM DUAL";
        case ODBC:
            return "SELECT 1";
        default:
            return "SELECT 1";
    }
}

void ConnectionPool::loadConfig()
{
    QString typeStr = ConfigHelper::instance().getString("database", "type", "sqlite").toLower();
    // 解析数据库类型
    if (typeStr == "sqlite") m_type = SQLite;
    else if (typeStr == "mysql") m_type = MySQL;
    else if (typeStr == "mariadb") m_type = MariaDB;
    else if (typeStr == "postgresql") m_type = PostgreSQL;
    else if (typeStr == "oracle") m_type = Oracle;
    else if (typeStr == "odbc") m_type = ODBC;
    else throw std::invalid_argument("Unsupported database type");

    // 加载通用配置
    m_dbName = ConfigHelper::instance().getString("database", "dbname", "");
    m_host = ConfigHelper::instance().getString("database", "host", "localhost");
    m_port = ConfigHelper::instance().getInt("database", "port", 0);
    m_user = ConfigHelper::instance().getString("database", "user", "");
    m_password = ConfigHelper::instance().getString("database", "password", "");
    m_maxConn = ConfigHelper::instance().getInt("database", "max_conn", 10);
    m_validationQuery = ConfigHelper::instance().getString("database", "validation_query", getDefaultValidationQuery());
}

QSqlDatabase ConnectionPool::createConnection()
{
    QString connName = QUuid::createUuid().toString();
    QSqlDatabase db = QSqlDatabase::addDatabase(driverName(), connName);
    QString options;
    // 通用配置
    switch(m_type)
    {
        case SQLite:
            db.setDatabaseName(m_dbName);
            // 增强 SQLite 连接选项
            options =
                "QSQLITE_BUSY_TIMEOUT=30000;"
                "QSQLITE_OPEN_URI;"
                "QSQLITE_ENABLE_SHARED_CACHE;"
                "QSQLITE_ENABLE_REGEXP;";
            db.setConnectOptions(options);
            break;
        case MySQL:
            db.setHostName(m_host);
            db.setPort(m_port);
            db.setUserName(m_user);
            db.setPassword(m_password);
            db.setDatabaseName(m_dbName);
            db.setConnectOptions("MYSQL_OPT_RECONNECT=1");
            break;
        case MariaDB:
            db.setHostName(m_host);
            db.setPort(m_port);
            db.setUserName(m_user);
            db.setPassword(m_password);
            db.setDatabaseName(m_dbName);
            break;
        case PostgreSQL:
            db.setHostName(m_host);
            db.setPort(m_port);
            db.setUserName(m_user);
            db.setPassword(m_password);
            db.setDatabaseName(m_dbName);
            break;
        case Oracle:
            db.setHostName(m_host);
            db.setPort(m_port);
            db.setUserName(m_user);
            db.setPassword(m_password);
            db.setDatabaseName(m_dbName); // 或使用 service name/SID
            break;
        case ODBC:
            // ODBC 连接字符串示例: "DRIVER={SQL Server};SERVER=server;DATABASE=db;UID=user;PWD=pass;"
            db.setDatabaseName(m_dbName); // m_dbName 应包含完整 ODBC 连接字符串
            break;
    }

    // 打开连接
    if (!db.open())
    {
        throw std::runtime_error("Connection failed: " + db.lastError().text().toStdString());
    }

    // 数据库特定初始化
    if (m_type == SQLite)
    {
        db.exec("PRAGMA journal_mode=WAL");
        db.exec("PRAGMA synchronous=NORMAL");
    }
    return db;

}

bool ConnectionPool::validateConnection(QSqlDatabase& conn)
{
    if(!conn.isOpen()) return false;

    QSqlQuery q(m_validationQuery, conn);
    if(!q.exec() || !q.next()) return false;

    // PostgreSQL特殊处理
    if(m_type == PostgreSQL)
    {
        QSqlQuery("DISCARD ALL", conn).exec();
    }
    return true;
}

bool ConnectionPool::beginTransaction()
{
    QMutexLocker lock( & m_transactionMutex);
    QSqlDatabase db = getConnection();
    if (db.transaction())
    {
        m_transactionStatus[db.connectionName()] = true;
        return true;
    }
    return false;
}

bool ConnectionPool::commitTransaction()
{
    QMutexLocker lock( & m_transactionMutex);
    QSqlDatabase db = QSqlDatabase::database();
    if (db.commit())
    {
        m_transactionStatus.remove(db.connectionName());
        return true;
    }
    return false;
}

bool ConnectionPool::rollbackTransaction()
{
    QMutexLocker lock( & m_transactionMutex);
    QSqlDatabase db = QSqlDatabase::database();
    if (db.rollback())
    {
        m_transactionStatus.remove(db.connectionName());
        return true;
    }
    return false;
}

void ConnectionPool::cleanupSession(QSqlDatabase& conn)
{
    QMutexLocker tLock( & m_transactionMutex);

    // 自动回滚未提交事务
    if (m_transactionStatus.contains(conn.connectionName()))
    {
        conn.rollback();
        m_transactionStatus.remove(conn.connectionName());
    }

    // 数据库特定清理
    switch(m_type)
    {
        case PostgreSQL:
            conn.exec("DISCARD ALL");
            break;
        case Oracle:
            conn.exec("ALTER SESSION CLOSE DATABASE LINK");
            break;
        case ODBC:
            // ODBC 可能需要重置会话状态
            conn.exec("RESET CONNECTION");
            break;
        case SQLite:
            // 重置 SQLite 连接状态
            conn.exec("ROLLBACK"); // 确保无活动事务
            conn.exec("PRAGMA optimize"); // 优化数据库
            conn.exec("PRAGMA wal_checkpoint(TRUNCATE)"); // 管理 WAL 文件
            // 重置繁忙处理
            conn.exec("PRAGMA busy_timeout=30000");
            break;
        default:
            break;
    }
}
